#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <unordered_map>
#include <fstream>
#include "Common.hpp"

const std::string Sep = "\r\n";
const std::string LineSep = " ";
const std::string HeadLineSep = ": ";
const std::string Defaulthomepage = "wwwroom";
const std::string Firstpag = "index.html";
const std::string Pag404 = "404.html";
const std::string http_version = "HTTP/1.1";
class HttpRequest
{
public:
    HttpRequest() {}
    ~HttpRequest() {}
    bool ItIsExec()
    {
        return _isexec;
    }
    // GET /favicon.ico HTTP/1.1
    // Host: 106.55.249.160:8080
    // Connection: keep-alive
    // User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
    // Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
    // Referer: http://106.55.249.160:8080/
    // Accept-Encoding: gzip, deflate
    // Accept-Language: zh-CN,zh;q=0.9
    bool SplistString(std::string &str, const std::string sep, std::string *key, std::string *value)
    {
        auto pos = str.find(sep);
        if (pos == std::string::npos)
            return false;
        *key = str.substr(0, pos);
        *value = str.substr(pos + sep.size());
        str.erase(0, pos + sep.size() + value->size());
        return true;
    }
    bool ParseHeaderKV()
    {
        std::string key, value;
        for (auto &line : _rep_header)
        {
            if (SplistString(line, HeadLineSep, &key, &value))
            {
                // _header_kv.insert(std::make_pair(key,value));
                _header_kv[key] = value;
            }
        }
        return true;
    }
    bool ParseHeader(std::string &request_str)
    {
        std::string line;
        while (ParseOneLine(request_str, &line, Sep))
        {
            if (line.empty())
            {
                // 空行，表示请求头结束
                _blank_line = Sep;
                break;
            }
            else
            {
                _rep_header.push_back(line);
            }
        }
        // 解析请求体 kay: vale
        ParseHeaderKV();
        return true;
    }

    // 获取请求行
    void Deserialize(std::string &request_str)
    {
        // 解析请求头
        if (ParseOneLine(request_str, &_req_line, Sep))
        {
            // 解析请求行
            ParseReqLine(_req_line, LineSep);
            // 解析请报求头
            ParseHeader(request_str);
            // 解析请求正文
            _body = request_str; // 直接将请求体赋值给_body,因为到这里只剩下请求体了

            // 分析请求中if有参数
            if (_method == "POST")
            {
                _isexec = true; // 参数为正文
                _args = _body;
                _path = _url;
            }
            else if (_method == "GET")
            {
                auto pos = _url.find("?");
                if (pos != std::string::npos)
                {
                    _isexec = true;
                    // /login?name=zhang&passwd=123456
                    _path = _url.substr(0, pos);
                    _args = _url.substr(pos + 1);
                }
            }
        }
    }

    std::string GetContent(const std::string path)
    {
        std::string content;
        std::ifstream in(path); // 打开请求文件
        if (!in.is_open())      // 请求文件不存在
            return std::string();
        std::string line;
        while (std::getline(in, line)) // 读取请求体
        {
            content += line; // 将请求体内容追加到content中
        }
        in.close();
        return content;
    }

    void ParseReqLine(std::string &req_line, const std::string LineSep)
    {
        std::stringstream req_line_stream(req_line);    // 将请求行转换为stringstream
        req_line_stream >> _method >> _url >> _version; // 解析请求行
    }
    void Print()
    {
        std::cout << "_method:" << _method << std::endl;
        std::cout << "_url:" << _url << std::endl;
        std::cout << "_version:" << _version << std::endl;

        for (auto &kv : _header_kv)
        {
            std::cout << kv.first << ": " << kv.second << std::endl;
        }
        std::cout << "_blank_line:" << _blank_line << std::endl;
        std::cout << "_body:" << _body << std::endl;
    }
    std::string Path()
    {
        return _path;
    }
    std::string Args()
    {
        return _args;
    }

    std::string Url()
    {
        return _url;
    }
    void SetUrl(const std::string &newurl)
    {
        _url = newurl;
    }
    std::string Suffix()
    {
        auto pos = _url.rfind(".");
        if (pos == std::string::npos)
            return std::string(".html");
        return _url.substr(pos + 1);
    }

private:
    std::string _req_line;
    std::vector<std::string> _rep_header;
    std::string _blank_line;
    std::string _body;

    // 第一行请求行的详细信息
    std::string _method;
    std::string _url;
    std::string _path;
    std::string _args;
    std::string _version;
    std::unordered_map<std::string, std::string> _header_kv;
    bool _isexec = false;
};

class HttpResponse
{
public:
    HttpResponse() : _verson(http_version), _blank_line(Sep)
    {
    }
    ~HttpResponse() {}
    void Bulid(HttpRequest &req)
    {
        std::string url = Defaulthomepage + req.Url();
        if (url.back() == '/') // 目录请求,尝试请求index.html
        {
            url += Firstpag;
            req.SetUrl(url); // 补全url
        }
        LOG(LogLevel::DEBUG) << "------客户端在请求: " << req.Url();
        req.Print();
        LOG(LogLevel::DEBUG) << "----------------------------";
        _content = req.GetContent(url);
        if (_content.empty())
        {
            _status_code = 404;
            req.SetUrl(Pag404);
            _content = req.GetContent(Pag404); // 404页面不存在时尝试请求404页面
        }
        else
        {
            _status_code = 200;
        }

        _status_dece = Code2Desc(_status_code);
        if (!_content.empty())
        {
            SetHeader("content-length", std::to_string(_content.size()));
        }
        std::string mime_tyoe = Suffix2Desc(req.Suffix()); // 根据url后缀获取mime_type

        SetHeader("content-type", mime_tyoe); // 设置响应头的content-type
        for (auto &kv : _header_kv)
        {
            _resp_header.push_back(kv.first + HeadLineSep + kv.second);
        }
    }

    void Serialize(std::string *response_str)
    {
        _resp_line = _verson + " " + std::to_string(_status_code) + " " + _status_dece + Sep;
        _body = _content;
        *response_str = _resp_line;
        for (auto &line : _resp_header)
        {
            *response_str += line + Sep;
        }
        *response_str += _blank_line;
        *response_str += _body;
    }
    void SetHeader(const std::string &key, const std::string &value)
    {
        _header_kv[key] = value;
    }

    std::string Code2Desc(int code)
    {
        switch (code)
        {
        case 200:
            return "OK";
            break;
        case 404:
            return "NOT FOUND";
            break;
        case 301:
            return "MOVED PERMANENTLY";
            break;
        case 302:
            return "FOUND";
            break;
        default:
            return std::string();
            break;
        }
        return std::string();
    }

    std::string Suffix2Desc(const std::string &suffix)
    {
        if (suffix == "html")
            return "text/html";
        else if (suffix == "css")
            return "text/css";
        else if (suffix == "js")
            return "text/javascript";
        else if (suffix == "png")
            return "image/png";
        else if (suffix == "jpg")
            return "image/jpg";
        else if (suffix == "gif")
            return "image/gif";
        else if (suffix == "ico")
            return "image/ico";
        else
            return std::string();
    }

private:
    std::string _resp_line;
    std::vector<std::string> _resp_header;
    std::string _blank_line;
    std::string _body;

    // 第一行响应行的详细信息
    std::string _verson;
    int _status_code;
    std::string _status_dece;
    std::string _content;
    std::unordered_map<std::string, std::string> _header_kv;
};